package com.hmkj.web.controller.simulation;

import com.hmkj.common.entity.ResultEntity;
import com.hmkj.common.utils.PriceHelper;
import com.hmkj.common.utils.StringUtils;
import com.hmkj.core.eolinker.endpoints.QuotationEndpoint;
import com.hmkj.core.eolinker.models.ModelRealTime;
import com.hmkj.core.exception.BussinessException;
import com.hmkj.core.model.index.OrderSimulationModel;
import com.hmkj.core.model.simulation.SubscribeModel;
import com.hmkj.core.model.simulation.UserSubscribeModel;
import com.hmkj.core.po.account.AccountSimulation;
import com.hmkj.core.po.simulation.OrderSimulation;
import com.hmkj.core.po.simulation.Subscribe;
import com.hmkj.core.po.simulation.UserSubscribe;
import com.hmkj.core.po.user.User;
import com.hmkj.core.service.simulation.OrderSimulationService;
import com.hmkj.core.service.simulation.SubscribeService;
import com.hmkj.core.service.simulation.UserSubscribeService;
import com.hmkj.core.service.user.UserService;
import com.hmkj.web.controller.GenericController;
import com.xiaoleilu.hutool.util.BeanUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * ......................我佛慈悲......................
 * ......................_oo0oo_.......................
 * .....................o8888888o......................
 * .....................88" . "88......................
 * .....................(| -_- |)......................
 * .....................0\  =  /0......................
 * ...................___/`---'\___....................
 * ..................' \\|     |// '...................
 * ................/ \\|||  :  |||// \.................
 * .............../ _||||| -卍-|||||- \................
 * ..............|   | \\\  -  /// |   |...............
 * ..............| \_|  ''\---/''  |_/ |...............
 * ..............\  .-\__  '-'  ___/-. /...............
 * ............___'. .'  /--.--\  `. .'___.............
 * .........."" '<  `.___\_<|>_/___.' >' ""............
 * ........| | :  `- \`.;`\ _ /`;.`/ - ` : | |.........
 * ........\  \ `_.   \_ __\ /__ _/   .-` /  /.........
 * ....=====`-.____`.___ \_____/___.-`___.-'=====......
 * ......................`=---='.......................
 * ....................................................
 * .................佛祖开光 ,永无BUG...................
 */
@Api(description = "订阅")
@Slf4j
@RestController
@RequestMapping(GenericController.MEMBER_URL + "/subscriber")
public class AppSubscribeController extends GenericController<Integer, AccountSimulation> {

    @Resource
    private UserSubscribeService userSubscribeService;
    @Resource
    private OrderSimulationService orderSimulationService;
    @Resource
    private SubscribeService subscribeService;
    @Resource
    private UserService userService;

    @ApiOperation(value = "订阅", notes = "订阅")
    @ResponseBody
    @RequestMapping(value = "/doSubscribe", method = RequestMethod.POST)
    public ResultEntity doScribe(@ApiParam("订单Id") @RequestParam(required = true) Integer id,
                                 @ApiParam("订阅状态 1:订阅， 2取消订阅") @RequestParam(required = true) String isSub) throws Exception {
        User user = getLoginUser();
        Subscribe subscribe = subscribeService.selectByPrimaryKey(id);
        if (subscribe == null) {
            throw new BussinessException("查询不到订阅人");
        }
        //查询是否有这条订阅记录
        UserSubscribe userSubscribe = userSubscribeService.selectOne(new UserSubscribe(t -> {
            t.setUserid(user.getId());
            t.setSubscriberId(subscribe.getId());
            t.setIsSub(UserSubscribe.ISSUB.T2.code);
        }));
        if (isSub.equals("1")) {
            if (userSubscribe != null) {
                throw new BussinessException("请勿重复订阅");
            }
            userSubscribeService.insert(new UserSubscribe(t -> {
                t.setUserid(user.getId());
                t.setSubscriberId(id);
                t.setIsSub(UserSubscribe.ISSUB.T2.code);
            }));
        } else {
            if (userSubscribe == null) {
                throw new BussinessException("请先订阅");
            }
            userSubscribeService.updateByPrimaryKeySelective(new UserSubscribe(t -> {
                t.setId(userSubscribe.getId());
                t.setIsSub(UserSubscribe.ISSUB.T1.code);
            }));
        }
        return ok("订阅成功",ResultEntity.SUCCESS);
    }


    @ApiOperation(value = "订阅的人列表", notes = "订阅的人列表")
    @ResponseBody
    @RequestMapping(value = "/listJson", method = RequestMethod.POST)
    public ResultEntity superiorList() throws Exception {
        User user = getLoginUser();
        List<UserSubscribe> list = userSubscribeService.select(new UserSubscribe(t -> {
            t.setUserid(user.getId());
            t.setIsSub(UserSubscribe.ISSUB.T2.code);
        }));
        List<UserSubscribeModel> modelList = new ArrayList();
        //查询用户订阅的人
        if (CollectionUtils.isNotEmpty(list)) {
            for (UserSubscribe subscribe : list) {
                UserSubscribeModel model = new UserSubscribeModel();
                BeanUtils.copyProperties(subscribe, model);
                Subscribe subs = subscribeService.selectByPrimaryKey(subscribe.getSubscriberId());
                User user1 = userService.selectByPrimaryKey(subs.getUserId());
                model.setAvatarUrl(user1.getAvatarUrl());
                model.setUserName(user1.getUserName());
                model.setId(user1.getId());
                modelList.add(model);
            }
        }
        return ok(m -> {
            m.put("subscriber", modelList);
        });
    }

    @ApiOperation(value = "高手推荐", notes = "高手推荐")
    @ResponseBody
    @RequestMapping(value = "/highLevelJson", method = RequestMethod.POST)
    public ResultEntity highLevel() throws Exception {
        User user = getLoginUser();
        List<Subscribe> list = subscribeService.select(new Subscribe(t -> {
            t.setHighLevel(Subscribe.HIGHLEVEL.T2.code);
        }));
        List<SubscribeModel> modelList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (Subscribe subscribe : list) {
                User user1 = userService.selectByPrimaryKey(subscribe.getUserId());
                SubscribeModel model = new SubscribeModel();
                BeanUtils.copyProperties(subscribe, model);
                //30天收益率
                Map param = new HashMap<>();
                param.put("userId", subscribe.getUserId());
                param.put("date", 30);
                param.put("status", OrderSimulation.STATUS.T7.code);
                BigDecimal totalBuy = BigDecimal.ZERO;
                BigDecimal totalWin = BigDecimal.ZERO;
                List<OrderSimulation> wins = orderSimulationService.selectOrderSimulateForTime(param);
                if (CollectionUtils.isNotEmpty(wins)) {
                    for (OrderSimulation order : wins) {
                        totalBuy = totalBuy.add(order.getTradeCredit());
                        totalWin = totalWin.add(order.getProfitCount());
                    }
                    model.setEarnings(PriceHelper.format(totalWin.divide(totalBuy.multiply(BigDecimal.valueOf(10000)), 4, RoundingMode.CEILING), 4));
                } else {
                    model.setEarnings(BigDecimal.valueOf(0));
                }
                //盈利策略数量
                List<OrderSimulation> win = orderSimulationService.selectProfitOrderSimulateForTime(param);
                if (CollectionUtils.isNotEmpty(win)) {
                    model.setWinRate(PriceHelper.format(BigDecimal.valueOf(win.size()).divide(BigDecimal.valueOf(orderSimulationService.selectCount(new OrderSimulation(t -> {
                        t.setUserId(subscribe.getUserId());
                        t.setStatus(OrderSimulation.STATUS.T7.code);
                    }))), 4, RoundingMode.CEILING), 4));
                } else {
                    model.setWinRate(BigDecimal.ZERO);
                }
                if (StringUtils.isNotBlank(user1.getAvatarUrl()) && StringUtils.isNotBlank(user1.getUserName())) {
                    model.setAvatarUrl(user1.getAvatarUrl());
                    model.setUserName(user1.getUserName());
                }
                if (user != null) {
                    //查询是否关注
                    UserSubscribe userSubscribe = userSubscribeService.selectOne(new UserSubscribe(t -> {
                        t.setUserid(user.getId());
                        t.setIsSub(UserSubscribe.ISSUB.T2.code);
                        t.setSubscriberId(subscribe.getId());
                    }));
                    model.setIsSub(null != userSubscribe ? 1 : 0);
                } else {
                    model.setIsSub(0);
                }
                modelList.add(model);
            }
            Collections.sort(modelList, (o1, o2) -> o2.getEarnings().compareTo(o1.getEarnings()));
        }
        return ok(modelList);
    }

    @ApiOperation(value = "订阅动态", notes = "订阅动态")
    @ResponseBody
    @RequestMapping(value = "/subDynamic", method = RequestMethod.POST)
    public ResultEntity subDynamic() throws Exception {
        User user = getLoginUser();
        //查询用户订阅的人
        List<OrderSimulationModel> simulations = new ArrayList<>();
        List<UserSubscribe> list = userSubscribeService.select(new UserSubscribe(t -> {
            t.setUserid(user.getId());
            t.setIsSub(UserSubscribe.ISSUB.T2.code);
        }));
        if (CollectionUtils.isNotEmpty(list)) {
            for (UserSubscribe subscribe : list) {
                Subscribe subs = subscribeService.selectByPrimaryKey(subscribe.getSubscriberId());
                //查找订阅用户当天的买入列表
                Map param = new HashMap();
                int[] status = new int[] {OrderSimulation.STATUS.T3.code,OrderSimulation.STATUS.T7.code};
                param.put("userId", subs.getUserId());
                param.put("date", 1);
                param.put("statuStr", status);
                List<OrderSimulation> orderSimulationList = orderSimulationService.selectOrderSimulateForTime(param);
                if (CollectionUtils.isNotEmpty(orderSimulationList)) {
                    for (OrderSimulation orderSimulation : orderSimulationList) {
                        OrderSimulationModel model = new OrderSimulationModel();
                        BeanUtils.copyProperties(orderSimulation, model);
                        User user1=userService.selectByPrimaryKey(orderSimulation.getUserId());
                        model.setUserName(user1.getUserName());
                        //查询涨幅比
                        ModelRealTime modelRealTime = QuotationEndpoint.realtime(orderSimulation.getEquityCode());
                        //没有查询到的默认给0 这个能查询到所有市场的股票吗？ //TODO
                        if (modelRealTime == null) {
                            model.setRise(BigDecimal.ZERO);
                        } else {
                            model.setRise(new BigDecimal(modelRealTime.getRise_pre()));
                        }
                        simulations.add(model);
                    }
                }

            }
        }
        return ok(simulations);
    }

    /**
     * 高手跟踪详情
     *
     * @param id 高手id
     */
    @ApiOperation(value = "高手跟踪详情", notes = "高手跟踪详情")
    @ResponseBody
    @RequestMapping(value = "/detailJson", method = RequestMethod.POST)
    public ResultEntity superiorDetail(@ApiParam("高手Id") @RequestParam(required = true) Integer id) throws Exception {
        Map<String, Object> data = new HashMap<>();
        if (StringUtils.isBlank(id)) {
            throw new BussinessException("参数错误");
        }
        Subscribe subscribe = subscribeService.selectByPrimaryKey(id);
        if (subscribe == null) {
            throw new BussinessException("高手不存在！");
        }
        //查询是否关注
        UserSubscribe userSubscribe = userSubscribeService.selectOne(new UserSubscribe(t->{
            t.setUserid(getLoginUser().getId());
            t.setSubscriberId(id);
            t.setIsSub(UserSubscribe.ISSUB.T2.code);
        }));
        if (userSubscribe != null) {
            data.put("isSub", userSubscribe.getIsSub());
        } else {
            data.put("isSub", 1);

        }
        User subscribeUser = userService.selectByPrimaryKey(subscribe.getUserId());
        data.put("name", subscribeUser.getUserName());
        data.put("avatarUrl",subscribeUser.getAvatarUrl());
        //总人气
        Integer count = userSubscribeService.selectCount(new UserSubscribe(t -> {
            t.setSubscriberId(subscribe.getId());
            t.setIsSub(UserSubscribe.ISSUB.T2.code);
        }));
        data.put("popular", count);
        //排名，收益率
        //日排名
        earningForTime(subscribe.getUserId(),1,data);
        //周排名
        earningForTime(subscribe.getUserId(),7,data);
        //月排名
        earningForTime(subscribe.getUserId(),30,data);
        //总排名，总收益
        earningForTime(subscribe.getUserId(),0,data);
        return ok(data);
    }

    /**
     * 计算收益率（总：null ,日：1,周：7，月：30）
     */
    private void earningForTime(Integer userId, Integer date, Map<String, Object> data) {
        //收益率
        Map param = new HashMap<>();
        param.put("userId", userId);
        param.put("date", date);
        param.put("status", OrderSimulation.STATUS.T7.code);
        BigDecimal earnings = BigDecimal.ZERO;
        List<OrderSimulation> wins = orderSimulationService.selectOrderSimulateForTime(param);
        if (CollectionUtils.isNotEmpty(wins)) {
            BigDecimal totalBuy = wins.stream().map(OrderSimulation::getTradeCredit).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalWin = wins.stream().map(OrderSimulation::getProfitCount).reduce(BigDecimal.ZERO, BigDecimal::add);
            earnings = PriceHelper.format(totalWin.divide(totalBuy.multiply(BigDecimal.valueOf(10000)), 4, RoundingMode.CEILING), 3);
        }
        if(0 == date){
            data.put("allEarning", earnings);
        }
        if (1 == date) {
            data.put("dayEarning", earnings);
        }
        if (7 == date) {
            data.put("weekEarning", earnings);
        }
        if(30 == date){
            data.put("monthEarning", earnings);
        }
        if(0 == date){
            List<Subscribe> subscribes = subscribeService.select(new Subscribe(t -> {
                t.setDelFlag(Subscribe.DELFLAG.NORMAL.code);
            }));
            List<SubscribeModel> subscribeModels = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(subscribes)) {
                for (Subscribe subscribe1 : subscribes) {
                    SubscribeModel model = new SubscribeModel();
                    BeanUtil.copyProperties(subscribe1, model);
                    //收益率
                    Map params = new HashMap<>();
                    params.put("userId", subscribe1.getUserId());
                    params.put("date", null);
                    params.put("status", OrderSimulation.STATUS.T7.code);
                    List<OrderSimulation> winss = orderSimulationService.selectOrderSimulateForTime(param);
                    if (CollectionUtils.isNotEmpty(wins)) {
                        BigDecimal totalBuy = winss.stream().map(OrderSimulation::getTradeCredit).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal totalWin = winss.stream().map(OrderSimulation::getProfitCount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        model.setEarnings(PriceHelper.format(totalWin.divide(totalBuy.multiply(BigDecimal.valueOf(10000)), 4, RoundingMode.CEILING), 3));
                    } else {
                        model.setEarnings(BigDecimal.valueOf(0));
                    }
                    subscribeModels.add(model);
                }
                Collections.sort(subscribeModels, (o1, o2) -> o2.getEarnings().compareTo(o1.getEarnings()));
            }
            if (subscribeModels.size() > 0) {
                for (int i = 0; i < subscribeModels.size(); i++) {
                    if (Objects.equals(subscribes.get(i).getUserId(), userId)) {
                        data.put("rank", i + 1);
                        break;
                    } else {
                        data.put("rank", "--");
                    }
                }
            } else {
                data.put("rank", "--");
            }
        }
    }

}
